package other.system.client.util;

import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.exception.XsyHttpException;
import com.rkhd.platform.sdk.http.CommonData;
import com.rkhd.platform.sdk.http.CommonHttpClient;
import com.rkhd.platform.sdk.http.CommonResponse;
import com.rkhd.platform.sdk.http.HttpResult;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class HttpUtils {
    private static Logger logger = LoggerFactory.getLogger();

    /**
     * 支持的Http method
     */
    private static enum HttpMethod {
        POST, DELETE, GET, PUT, HEAD;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static String invokeUrl(String url, Map params, Map<String, String> headers, Integer connectTimeout, Integer readTimeout, String encoding, HttpMethod method) {
        CommonData.Builder req = CommonData.newBuilder();
        req.callString(url);
        req.callType(method.name());
        req.formType("urlEncoded");

        if (headers != null) req.header(headers);
        if (params != null) req.formData(params);

        try {
            CommonHttpClient httpClient = CommonHttpClient.instance();
            CommonResponse<String> result = httpClient.execute(req.build(), e -> e);
            return result.getData();
        } catch (XsyHttpException e) {
            logger.error("调用接口[" + url + "]失败！请求URL：" + url + "，参数：" + params + ";错误信息：" + e.getMessage(), e);
        }
        return null;
    }


    /**
     * POST方法提交Http请求，语义为“增加” <br/>
     * 注意：Http方法中只有POST方法才能使用body来提交内容
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String post(String url, Map params, Map<String, String> headers, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, headers, connectTimeout, readTimeout, charset, HttpMethod.POST);
    }

    public static String post(String url, Map params) {
        return invokeUrl(url, params, null, null, null, null, HttpMethod.POST);
    }

    /**
     * GET方法提交Http请求，语义为“查询”
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String get(String url, Map params, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, null, connectTimeout, readTimeout, charset, HttpMethod.GET);
    }

    /**
     * GET方法提交Http请求，语义为“查询”
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String get(String url, Map params, Map<String, String> headers, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, headers, connectTimeout, readTimeout, charset, HttpMethod.GET);
    }

    /**
     * PUT方法提交Http请求，语义为“更改” <br/>
     * 注意：PUT方法也是使用url提交参数内容而非body，所以参数最大长度收到服务器端实现的限制，Resin大概是8K
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String put(String url, Map params, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, null, connectTimeout, readTimeout, charset, HttpMethod.PUT);
    }

    /**
     * PUT方法提交Http请求，语义为“更改” <br/>
     * 注意：PUT方法也是使用url提交参数内容而非body，所以参数最大长度收到服务器端实现的限制，Resin大概是8K
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String put(String url, Map params, Map<String, String> headers, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, headers, connectTimeout, readTimeout, charset, HttpMethod.PUT);
    }

    /**
     * DELETE方法提交Http请求，语义为“删除”
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String delete(String url, Map params, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, null, connectTimeout, readTimeout, charset, HttpMethod.DELETE);
    }

    /**
     * DELETE方法提交Http请求，语义为“删除”
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String delete(String url, Map params, Map<String, String> headers, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, headers, connectTimeout, readTimeout, charset, HttpMethod.DELETE);
    }

    /**
     * HEAD方法提交Http请求，语义同GET方法  <br/>
     * 跟GET方法不同的是，用该方法请求，服务端不返回message body只返回头信息，能节省带宽
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String head(String url, Map params, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, null, connectTimeout, readTimeout, charset, HttpMethod.HEAD);
    }

    /**
     * HEAD方法提交Http请求，语义同GET方法  <br/>
     * 跟GET方法不同的是，用该方法请求，服务端不返回message body只返回头信息，能节省带宽
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头参数
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @param charset        字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String head(String url, Map params, Map<String, String> headers, int connectTimeout, int readTimeout, String charset) {
        return invokeUrl(url, params, headers, connectTimeout, readTimeout, charset, HttpMethod.HEAD);
    }

    /**
     * 发起外部请求
     *
     * @param url
     * @param requestData 发送的数据
     * @param parame      参数
     * @return
     * @throws Exception
     */
    public static JSONObject sendPostRequest(String url, JSONObject requestData, Map<String, String> parame) throws Exception {
        CommonData data = new CommonData();
        if (parame != null && parame.size() > 0) {
            StringBuilder stringBuilder = new StringBuilder(url);
            stringBuilder.append("?");
            parame.forEach((k, v) -> {
                stringBuilder.append(k);
                stringBuilder.append("=");
                stringBuilder.append(v);
                stringBuilder.append("&");
            });
            String parameStr = stringBuilder.toString();
            url = parameStr.substring(0, parameStr.length() - 1);
        }
        data.setCallString(url);
        data.setCall_type(HttpMethod.POST.name());

        // 使用json时的设置
        data.putHeader("Content-Type", "application/json");
        data.setBody(requestData == null ? null : requestData.toJSONString());

        HttpResult respStr = CommonHttpClient.instance().execute(data);
        JSONObject result = JSONObject.parseObject(respStr.getResult());
        return result;
    }

    public static JSONObject sendPostRequest(String url, JSONObject requestData) throws Exception {
        return sendPostRequest(url, requestData, null);
    }

    public static JSONObject sendPostRequest(String url, Map<String, String> parame) throws Exception {
        return sendPostRequest(url, null, parame);
    }

    public static void main(String[] args) throws Exception {
        String url = "http://495441r29g.qicp.vip/paas/controller/testMethod";

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("dizi", "龙岗");
        jsonObject.put("aihao", "打篮球");
        jsonObject.put("age", 0);

        Map<String, String> map = new HashMap<>();
        map.put("name", "张三");
        map.put("sex", "男");
        JSONObject jsonObject1 = sendPostRequest(url, jsonObject, map);
//        JSONObject jsonObject1 = sendPostRequest(url, jsonObject, null);

        System.out.println(jsonObject1);
    }


//    public static void main(String[] args) {
//        Map<String, String> params = new HashMap<>();
//        params.put("id", "post");
//        //String str = HttpUtils.get("http://www.test.cn/html/2019-3-19/postTest.php", params, 3000, 3000, "UTF-8");
//        String str = HttpUtils.post("http://www.test.cn/html/2019-3-19/postTest.php", params, 3000, 3000, "UTF-8");
//        System.out.println(str);
//    }
}
